export { }
// Proxy 代理
interface Props {
  name: string
  age: number
}
let props: Props = {
  name: 'smd',
  age: 18
}
type Proxy<T> = {
  get(): T
  set(value: T): void
}
type Proxify<T> = {
  [P in keyof T]: Proxy<T[P]>
}
function proxify<T>(obj: T): Proxify<T> {
  let rest = {} as Proxify<T>
  for (const key in obj) {
    rest[key] = {
      get() {
        return obj[key]
      },
      set(value) {
        obj[key] = value
      }
    }
  }
  return rest
}

let proxyProps = proxify(props)
console.log(proxyProps);

// 取消代理
function unProxify<T>(t: Proxify<T>): T {
  let rest = {} as T
  for (const key in t) {
    rest[key] = t[key].get()
  }

  return rest
}

let originProps = unProxify(proxyProps)
console.log(originProps);

// setDifference    
type setDifference<A, B> = A extends B ? never : A  // 返回 A类型中 B没有的部分
type A = string | number
type B = number | boolean
type ab = setDifference<A, B>  // ab: string

// Omit  忽略
type Omit<T, K extends keyof any> = Pick<T, setDifference<keyof T, K>>
type params = { name: string, age: number, visible: boolean }
type OmitParams = Omit<params, 'age'>
// type OmitParams = {
//   name: string;
//   visible: boolean;
// }
/**
 * 分析
 *  Omit<params, 'age'>
 *  T为   { name: string, age: number, visible: boolean }
 *  
 *  K为  string  number symbol
 * 
 * setDifference<keyof T, K>     keyof T 为 [ name, age, visible ]  与 age 的结果 是 name  visible
 * 最后经过Pick 将name visible提取出来
 */

// Diff  从T中排除掉U中的类型
type Params1 = { name: string, age: number, visible: boolean }
type Params11 = { age: number }
type Diff<T extends object, U extends object> = Pick<T, setDifference<keyof T, keyof U>>

type Params1Diff = Diff<Params1, Params11>


namespace na {
  // InterSection 交集
  type InterSection<T extends object, U extends object> = Pick<T, Extract<keyof T, keyof U> & Extract<keyof U, keyof T>>;
  type Params1 = { name: string, age: number, visible: boolean }
  type Params11 = { age: number }
  type NewInterSection = InterSection<Params1, Params11> // age
}
namespace nb {
  // Overwrite  重写
  type Props = { name: string, age: number, visible: boolean }
  type NewProps = { age: string, other: string }
  type InterSection<T extends object, U extends object> = Pick<T, Extract<keyof T, keyof U> & Extract<keyof U, keyof T>>;
  type Overwrite<T extends object, U extends object, I = Diff<T, U> & InterSection<U, T>> = Pick<I, keyof I>
  // { name: string, age: string, visible: boolean }
  type ReplaceProps = Overwrite<Props, NewProps>

}

namespace mg {
  // Merge 合并 = Compute + Omit<U,T>
  type O1 = {
    id: number
    name: string
  }
  type O2 = {
    id: number
    age: number
  }

  // type R2 = Merge<O1, O2>
  type Compute<A extends any> = A extends Function ? A : { [K in keyof A]: A[K] }
  type R1 = Compute<{ x: 'x' } & { y: 'y' }>
  type Merge<T extends object, R extends object> = Compute<T & Omit<R, keyof T>>
  type R2 = Merge<O1, O2> // {id: number; name: string; age: number;}

}